all repos — caroster @ 9149587136874e250bdc8994451e13889b029762

[Octree] Group carpool to your event https://caroster.io

frontend/pages/e/[uuid].tsx (view raw)

  1import {useState, useReducer, useEffect} from 'react';
  2import {useTranslation} from 'react-i18next';
  3import Layout from '../../layouts/Default';
  4import Fab from '../../containers/Fab';
  5import CarColumns from '../../containers/CarColumns';
  6import NewCarDialog from '../../containers/NewCarDialog';
  7import AddToMyEventDialog from '../../containers/AddToMyEventDialog';
  8import EventBar from '../../containers/EventBar';
  9import useToastStore from '../../stores/useToastStore';
 10import {initializeApollo} from '../../lib/apolloClient';
 11import ErrorPage from '../_error';
 12import {
 13  useUpdateEventMutation,
 14  Event as EventType,
 15  useEventByUuidQuery,
 16  EventByUuidDocument,
 17} from '../../generated/graphql';
 18import useEventStore from '../../stores/useEventStore';
 19import Loading from '../../containers/Loading';
 20
 21const POLL_INTERVAL = 10000;
 22
 23interface Props {
 24  event: EventType;
 25  eventUUID: string;
 26}
 27
 28const EventPage = props => {
 29  const {event} = props;
 30  const {t} = useTranslation();
 31
 32  if (!event) return <ErrorPage statusCode={404} title={t`event.not_found`} />;
 33
 34  return <Event {...props} />;
 35};
 36
 37const Event = (props: Props) => {
 38  const {eventUUID} = props;
 39  const {t} = useTranslation();
 40  const addToast = useToastStore(s => s.addToast);
 41  const setEvent = useEventStore(s => s.setEvent);
 42  const eventUpdate = useEventStore(s => s.event);
 43  const setIsEditing = useEventStore(s => s.setIsEditing);
 44  const [updateEvent] = useUpdateEventMutation();
 45  const [isAddToMyEvent, setIsAddToMyEvent] = useState(false);
 46  const [openNewCar, toggleNewCar] = useReducer(i => !i, false);
 47  const {data: {eventByUUID: event} = {}} = useEventByUuidQuery({
 48    pollInterval: POLL_INTERVAL,
 49    variables: {uuid: eventUUID},
 50  });
 51
 52  useEffect(() => {
 53    if (event) setEvent(event as EventType);
 54  }, [event]);
 55
 56  const onSave = async e => {
 57    try {
 58      const {id, ...data} = eventUpdate;
 59      delete data.__typename;
 60      delete data.cars;
 61      delete data.waitingList;
 62      await updateEvent({variables: {id, eventUpdate: data}});
 63      setIsEditing(false);
 64    } catch (error) {
 65      console.error(error);
 66      addToast(t('event.errors.cant_update'));
 67    }
 68  };
 69
 70  const onShare = async () => {
 71    if (!event) return null;
 72    // If navigator as share capability
 73    if (!!navigator.share)
 74      return await navigator.share({
 75        title: `Caroster ${event.name}`,
 76        url: `${window.location.href}`,
 77      });
 78    // Else copy URL in clipboard
 79    else if (!!navigator.clipboard) {
 80      await navigator.clipboard.writeText(window.location.href);
 81      addToast(t('event.actions.copied'));
 82      return true;
 83    }
 84  };
 85
 86  if (!event) return <Loading />;
 87
 88  return (
 89    <Layout
 90      pageTitle={t('event.title', {title: event.name})}
 91      menuTitle={t('event.title', {title: event.name})}
 92      displayMenu={false}
 93    >
 94      <EventBar
 95        event={event}
 96        onAdd={setIsAddToMyEvent}
 97        onSave={onSave}
 98        onShare={onShare}
 99      />
100      <CarColumns toggleNewCar={toggleNewCar} />
101      <Fab onClick={toggleNewCar} open={openNewCar} aria-label="add-car" />
102      <NewCarDialog open={openNewCar} toggle={toggleNewCar} />
103      <AddToMyEventDialog
104        event={event}
105        open={isAddToMyEvent}
106        onClose={() => setIsAddToMyEvent(false)}
107      />
108    </Layout>
109  );
110};
111
112export async function getServerSideProps(ctx) {
113  const {uuid} = ctx.query;
114  const apolloClient = initializeApollo();
115  const {data = {}} = await apolloClient.query({
116    query: EventByUuidDocument,
117    variables: {uuid},
118  });
119  const {eventByUUID: event} = data;
120  const {host = ''} = ctx.req.headers;
121
122  return {
123    props: {
124      event,
125      eventUUID: uuid,
126      metas: {
127        title: event?.name || '',
128        url: `https://${host}${ctx.resolvedUrl}`,
129      },
130    },
131  };
132}
133
134export default EventPage;